#include "BaseNode.h"
#include "BasePort.h"
#include "DataPort.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QBrush>
#include <QPen>
#include <QColor>
#include <QFont>
#include <QGraphicsTextItem>

BaseNode::BaseNode()
    : m_portsAddedToScene(false)
{
    // 1. 初始化节点尺寸
    m_width = 120.0;   // 节点宽度120像素
    m_height = 60.0;   // 节点高度60像素
    
    // 2. 设置节点交互标志
    setFlags(QGraphicsItem::ItemIsMovable |          // 可移动
             QGraphicsItem::ItemIsSelectable |       // 可选择  
             QGraphicsItem::ItemSendsGeometryChanges); // 几何变化时发送信号
    
    // 3. 设置默认节点名称
    m_nodeName = "Base Node";
}

BaseNode::~BaseNode()
{
    // 清理所有端口
    qDeleteAll(m_inputPorts);
    qDeleteAll(m_outputPorts);
}

QRectF BaseNode::boundingRect() const
{
    // 返回以(0,0)为左上角，宽度m_width，高度m_height的矩形
    return QRectF(0, 0, m_width, m_height);
}

void BaseNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    // 1. 设置抗锯齿渲染
    painter->setRenderHint(QPainter::Antialiasing);
    
    // 2. 绘制节点背景（圆角矩形）
    //    - 背景色：调用子类的getNodeColor()获取
    //    - 圆角半径：8像素
    QRectF rect = boundingRect();
    painter->setBrush(QBrush(getNodeColor()));
    painter->setPen(QPen(QColor(200, 200, 200), 2)); // 浅灰色边框，2像素宽
    painter->drawRoundedRect(rect, 8, 8);
    
    // 3. 绘制节点名称文本
    //    - 颜色：白色
    //    - 字体：默认字体
    //    - 位置：居中显示
    painter->setPen(Qt::white);
    painter->drawText(rect, Qt::AlignCenter, getNodeType()); // 显示节点类型作为标题
}

QVariant BaseNode::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if (change == ItemSceneChange) {
        // 当节点即将被添加到场景或从场景中移除时
        if (value.value<QGraphicsScene*>() != nullptr) {
            // 节点即将被添加到场景
            // 确保端口也被添加到场景
            ensurePortsInScene();
        }
    } else if (change == ItemPositionHasChanged) {
        // 当节点位置改变时，更新所有端口的位置
        updatePortPositions();
    }
    
    return QGraphicsItem::itemChange(change, value);
}

void BaseNode::executeNode()
{
    // 按顺序调用三个方法，体现模板方法模式
    preProcess();    // 前处理
    processLogic();  // 核心逻辑（由子类实现）
    postProcess();   // 后处理
}

void BaseNode::preProcess()
{
    // 执行前的准备工作 - 暂时留空，子类可以重写
    // 例如：清理之前的计算结果、重置状态等
}

void BaseNode::postProcess()
{
    // 执行后的清理工作 - 暂时留空，子类可以重写  
    // 例如：更新UI显示、通知其他组件等
}

BasePort* BaseNode::addPort(PortType type, const QString& dataType)
{
    // 创建新端口
    DataPort* port = new DataPort(this, type, dataType);
    
    // 根据端口类型添加到相应的列表
    if (type == PortType::Input) {
        m_inputPorts.append(port);
    } else {
        m_outputPorts.append(port);
    }
    
    // 计算端口位置（相对于节点）
    qreal portY = 20.0; // 默认Y位置
    if (type == PortType::Input) {
        // 输入端口放在左侧，垂直排列
        portY = 20.0 + (m_inputPorts.size() - 1) * 20;
        port->setPos(0, portY);  // 相对于节点的左侧
    } else {
        // 输出端口放在右侧，垂直排列
        portY = 20.0 + (m_outputPorts.size() - 1) * 20;
        port->setPos(m_width, portY);  // 相对于节点的右侧
    }
    
    // 将端口添加到场景（如果节点已经在场景中）
    ensurePortsInScene();
    
    return port;
}

QList<BasePort*> BaseNode::getInputPorts() const
{
    return m_inputPorts;
}

QList<BasePort*> BaseNode::getOutputPorts() const
{
    return m_outputPorts;
}

void BaseNode::removePort(BasePort* port)
{
    if (!port) return;
    
    // 从列表中移除端口
    m_inputPorts.removeAll(port);
    m_outputPorts.removeAll(port);
    
    // 从场景中移除端口
    if (port->scene()) {
        port->scene()->removeItem(port);
    }
    
    // 删除端口对象
    delete port;
}

void BaseNode::ensurePortsInScene()
{
    // 如果节点已经在场景中，则添加所有端口到场景
    if (scene()) {
        // 添加所有输入端口
        for (BasePort* port : m_inputPorts) {
            if (!port->scene()) {
                scene()->addItem(port);
            }
        }
        
        // 添加所有输出端口
        for (BasePort* port : m_outputPorts) {
            if (!port->scene()) {
                scene()->addItem(port);
            }
        }
        
        // 注意：不要设置m_portsAddedToScene为true，因为我们需要确保每次节点在场景中时都能正确添加端口
    }
}

void BaseNode::updatePortPositions()
{
    // 更新所有输入端口的位置
    for (int i = 0; i < m_inputPorts.size(); ++i) {
        BasePort* port = m_inputPorts[i];
        qreal portY = 20.0 + i * 20;
        port->setPos(0, portY);  // 相对于节点的左侧
    }
    
    // 更新所有输出端口的位置
    for (int i = 0; i < m_outputPorts.size(); ++i) {
        BasePort* port = m_outputPorts[i];
        qreal portY = 20.0 + i * 20;
        port->setPos(m_width, portY);  // 相对于节点的右侧
    }
}